﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using CkSoftware.GroupMe.Sdk.Core.Dao;

namespace CkSoftware.GroupMe.Sdk.Helpers.Emoji
{
	/// <summary>
	/// Provides static methods to render the emoji images into a message.
	/// </summary>
	public static class GroupMeEmojiMessageRenderer
	{
		private const string InlineHtmlEmojiFormat =
			@"<span style=""background:url('{0}') no-repeat -{1}px -{2}px;display:inline-block;height:{3}px;width:{4}px;vertical-align:top;""></span>";

		private const string OptimizedHtmlEmojiFormat =
			@"<span class=""emoji emoji-pack-{0}"" style=""background-position: -{1}px -{2}px;""></span>";

		/// <summary>
		/// Merges the emoji images with the message using a emojiToString converter func. The default converter is the
		/// <see cref="DefaultHtmlInlineCssConverter" />.
		/// </summary>
		/// <param name="message">The message to parse and to enrich with the emoji images.</param>
		/// <param name="emojiAttachment">The original emoji message attachment.</param>
		/// <param name="emojiToStringConverter">
		/// The converter to render <see cref="GroupMeEmojiImage" /> instances into a string.
		/// Default converter is the Method <see cref="DefaultHtmlInlineCssConverter" />, for optimized html output use
		/// <see cref="OptimizedHtmlCssConverter" /> or an own implementation if you need any other placeholders in the output
		/// string.
		/// </param>
		/// <returns>The enriched message containing all emoji images rendered using the emojiToStringConverter parameter.</returns>
		public static string MergeMessageWithEmojiImages(string message, GroupMeEmojiAttachment emojiAttachment,
			Func<GroupMeEmojiImage, string> emojiToStringConverter = null)
		{
			if (emojiAttachment == null)
			{
				return message;
			}

			IEnumerable<GroupMeEmojiImage> emojiImages = GroupMeEmojiImageParser.ParseImages(emojiAttachment.EmojiMap);
			return MergeMessageWithEmojiImages(message, emojiAttachment.EmojiPlaceholder, emojiImages, emojiToStringConverter);
		}

		/// <summary>
		/// Merges the emoji images with the message using a emojiToString converter func. The default converter is the
		/// <see cref="DefaultHtmlInlineCssConverter" />.
		/// </summary>
		/// <param name="message">The message to parse and to enrich with the emoji images.</param>
		/// <param name="emojiPlaceholder">The Placeholder character which is used inside the message.</param>
		/// <param name="emojiImages">The list of already parsed <see cref="GroupMeEmojiImage" />.</param>
		/// <param name="emojiToStringConverter">
		/// The converter to render <see cref="GroupMeEmojiImage" /> instances into a string.
		/// Default converter is the Method <see cref="DefaultHtmlInlineCssConverter" />, for optimized html output use
		/// <see cref="OptimizedHtmlCssConverter" /> or an own implementation if you need any other placeholders in the output
		/// string.
		/// </param>
		/// <returns>The enriched message containing all emoji images rendered using the emojiToStringConverter parameter.</returns>
		public static string MergeMessageWithEmojiImages(string message, char emojiPlaceholder,
			IEnumerable<GroupMeEmojiImage> emojiImages, Func<GroupMeEmojiImage, string> emojiToStringConverter = null)
		{
			if (emojiImages == null)
			{
				return message;
			}

			if (emojiToStringConverter == null)
			{
				emojiToStringConverter = DefaultHtmlInlineCssConverter;
			}

			var output = new StringBuilder();
			GroupMeEmojiImage[] emojiArray = emojiImages.ToArray();

			int currentEmojiIndex = 0;
			foreach (char chr in message)
			{
				if (chr.Equals(emojiPlaceholder))
				{
					output.Append(emojiToStringConverter(emojiArray[currentEmojiIndex]));
					currentEmojiIndex++;
				}
				else
				{
					output.Append(chr);
				}
			}

			return output.ToString();
		}

		/// <summary>
		/// Default emoji to html converter which creates a span with the needed styles to display the emoji as background-image.
		/// </summary>
		/// <param name="image">The emoji image to convert to HTML.</param>
		/// <returns>The html representation to add to the content.</returns>
		public static string DefaultHtmlInlineCssConverter(GroupMeEmojiImage image)
		{
			return string.Format(
				CultureInfo.CurrentCulture,
				InlineHtmlEmojiFormat,
				image.PackSpriteImageUrl,
				image.LeftPosition,
				image.TopPosition,
				image.IconHeight,
				image.IconWidth);
		}

		/// <summary>
		/// Emoji to html converter which creates a span with a css-class 'emoji' and a css-class 'emoji-pack-X' (X is replaced
		/// with the pack-name) and only adds the background-position as style attribute. Assumes that the .emoji and .emoji-pack-x
		/// classes are styled correctly using CSS.
		/// </summary>
		/// <param name="image">The emoji image to convert to HTML.</param>
		/// <returns>The optimized html representation of the image to add to the content.</returns>
		public static string OptimizedHtmlCssConverter(GroupMeEmojiImage image)
		{
			return string.Format(
				CultureInfo.CurrentCulture,
				OptimizedHtmlEmojiFormat,
				image.Definition.PackId,
				image.LeftPosition,
				image.TopPosition);
		}
	}
}